// Copyright Epic Games, Inc. All Rights Reserved.

#include "AbilitySystem/Abilities/LyraGameplayAbility_Reset.h"

#include "AbilitySystem/LyraAbilitySystemComponent.h"
#include "Character/LyraCharacter.h"
#include "GameFramework/GameplayMessageSubsystem.h"
#include "LyraGameplayTags.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraGameplayAbility_Reset)

/**
 * 构造函数
 *
 * @param ObjectInitializer 用于属性初始化的对象初始化器
 */
ULyraGameplayAbility_Reset::ULyraGameplayAbility_Reset(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer) // 调用父类构造函数
{
	InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor; // 设置实例化策略为每个执行者实例化
	NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerInitiated; // 设置网络执行策略为服务器发起

	if (HasAnyFlags(RF_ClassDefaultObject)) // 如果是类默认对象（CDO）
	{
		// 将能力触发标签作为默认值添加到CDO中
		FAbilityTriggerData TriggerData;
		TriggerData.TriggerTag = LyraGameplayTags::GameplayEvent_RequestReset; // 设置触发标签
		TriggerData.TriggerSource = EGameplayAbilityTriggerSource::GameplayEvent; // 设置触发源为游戏玩法事件
		AbilityTriggers.Add(TriggerData); // 添加触发数据到能力触发器列表
	}
}

/**
 * 激活能力
 *
 * @param Handle 能力规格句柄
 * @param ActorInfo 能力执行者信息
 * @param ActivationInfo 能力激活信息
 * @param TriggerEventData 触发能力的事件数据
 */
void ULyraGameplayAbility_Reset::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	check(ActorInfo); // 检查执行者信息是否有效

	ULyraAbilitySystemComponent* LyraASC = CastChecked<ULyraAbilitySystemComponent>(ActorInfo->AbilitySystemComponent.Get()); // 获取并转换为Lyra能力系统组件

	FGameplayTagContainer AbilityTypesToIgnore; // 创建要忽略的能力类型容器
	AbilityTypesToIgnore.AddTag(LyraGameplayTags::Ability_Behavior_SurvivesDeath); // 添加"存活死亡"行为标签到忽略容器

	// 取消所有能力并阻止其他能力启动
	LyraASC->CancelAbilities(nullptr, &AbilityTypesToIgnore, this);

	SetCanBeCanceled(false); // 设置此能力不能被取消

	// 从角色执行重置
	if (ALyraCharacter* LyraChar = Cast<ALyraCharacter>(CurrentActorInfo->AvatarActor.Get())) // 获取当前角色
	{
		LyraChar->Reset(); // 调用角色的重置方法
	}

	// 让其他系统知道发生了重置
	FLyraPlayerResetMessage Message;
	Message.OwnerPlayerState = CurrentActorInfo->OwnerActor.Get(); // 设置消息的拥有者玩家状态
	UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(this); // 获取游戏消息子系统
	MessageSystem.BroadcastMessage(LyraGameplayTags::GameplayEvent_Reset, Message); // 广播重置消息

	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData); // 调用父类的激活能力方法

	const bool bReplicateEndAbility = true; // 设置需要复制结束能力
	const bool bWasCanceled = false; // 设置未被取消
	EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicateEndAbility, bWasCanceled); // 结束能力
}